package cur.nature.gateway.common.config;


import cur.nature.framework.core.thread.MyThreadLocal;
import cur.nature.framework.core.util.CollectUtil;
import cur.nature.framework.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@Component
public class GlobalTraceIdFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 如果 trace_id不存在,则创建
        final List<String> traceIdList = request.getHeaders().get(MyThreadLocal.TRACE_ID);
        final String traceId = CollectUtil.isNotEmpty(traceIdList)?traceIdList.getFirst() : IdUtil.generate() +"";
        // 加入 request header
        if (CollectUtil.isEmpty(traceIdList)) {
            request = exchange.getRequest().mutate().header(MyThreadLocal.TRACE_ID, traceId).build();
            exchange = exchange.mutate().request(request).build();
        }
        // 放入线程
        MyThreadLocal.getCurrentThread().put(MyThreadLocal.TRACE_ID, traceId);
        log.info("Method: {}, URL: {}", request.getMethod(), request.getPath().value());
        // 传递
        final ServerWebExchange finalExchange = exchange;
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 加入 response header
            final HttpHeaders headers = finalExchange.getResponse().getHeaders();
            if (CollectUtil.isEmpty(headers.get(MyThreadLocal.TRACE_ID))) {
                headers.add(MyThreadLocal.TRACE_ID, traceId); // 添加自定义的响应头参数
            }
        }));
    }



    @Override
    public int getOrder() {
        // 这个地方非常坑，一定要小于-1才会进入到response 的代理中，因为 NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER 的值是-1, 如果大于它, NettyWriteResponseFilter 会直接返回，就不会执行自己定义的response.大坑，在这里用@Order好像不好使， 得实现Ordered 接口
//        return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
        return -5;
    }

}
